package com.koko.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.koko.constant.FileNameConstant;
import com.koko.constant.MessageConstant;
import com.koko.context.AdminContext;
import com.koko.exception.AccountPermissionInsufficientException;
import com.koko.game.dto.*;
import com.koko.game.entity.*;
import com.koko.game.vo.*;
import com.koko.mapper.GameCategoryMapper;
import com.koko.mapper.GameMapper;
import com.koko.mapper.GamePublisherMapper;
import com.koko.result.PageResult;
import com.koko.service.*;
import com.koko.utils.IOUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class GameServiceImpl implements GameService {
    @Value("${koko.path.game}")
    private String basePath;
    @Autowired
    private GameMapper gameMapper;
    @Autowired
    private GamePriceService gamePriceService;
    @Autowired
    private GameDetailService gameDetailService;
    @Autowired
    private GameViewService gameViewService;
    @Autowired
    private GameRequireService gameRequireService;
    @Autowired
    private GamePublisherMapper gamePublisherMapper;
    @Autowired
    private GameCategoryMapper gameCategoryMapper;
    @Autowired
    private GameCommentService gameCommentService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private PublisherService publisherService;

    /**
     * 分页查询
     * @param gamePageQueryDTO
     * @return
     */
    @Override
    public Page<Game> pageQuery(GamePageQueryDTO gamePageQueryDTO) {
        PageHelper.startPage(gamePageQueryDTO.getPage(), gamePageQueryDTO.getPageSize());
        return gameMapper.pageQuery(gamePageQueryDTO);
    }

    /**
     * 保存游戏
     * @param gameAddDTO
     * @return
     */
    @Override
    @Transactional
    public Long save(GameAddDTO gameAddDTO) {
        Game game = new Game();
        BeanUtils.copyProperties(gameAddDTO, game);
        // 1. 先插入游戏
        gameMapper.insert(game);
        Long id = game.getId();
        // 2. 再插入游戏发行商关系表
        GamePublisher gamePublisher = new GamePublisher();
        gamePublisher.setGameId(id);
        gamePublisher.setPublisherId(gameAddDTO.getPublisher().getId());
        gamePublisherMapper.insert(gamePublisher);
        // 3.在磁盘中创建相关文件夹
        IOUtil.createDirectory(basePath + id);
        IOUtil.createDirectory(basePath + id + "/" + FileNameConstant.GAME_FOLDER_NAME);
        IOUtil.createTxtFile(basePath + id + "/", FileNameConstant.GAME_INTRODUCTION);
        IOUtil.createTxtFile(basePath + id + "/", FileNameConstant.GAME_DESCRIPTION);
        return id;
    }

    /**
     * 删除游戏
     * @param ids
     */
    @Override
    @Transactional
    public void deleteBatch(List<Long> ids) {
        // 当前管理员权限验证
        adminPermission();
        for (Long id : ids) {
            // 1. 删除游戏发行商关系表
            gamePublisherMapper.deleteByGameId(id);
            // 2. 删除游戏分类关系表
            gameCategoryMapper.deleteByGameId(id);
            // 3. 删除游戏价格表
            gamePriceService.deleteByGameId(id);
            // 4. 删除游戏详细表
            gameDetailService.deleteByGameId(id);
            // 5. 删除游戏图片视频表
            gameViewService.deleteByGameId(id);
            // 6. 删除游戏配置表
            gameRequireService.deleteByGameId(id);
            // 7. 删除游戏评论表
            gameCommentService.deleteByGameId(id);
            // 8. 删除游戏表
            gameMapper.deleteById(id);
            // 9. 删除文件夹
            IOUtil.deleteFileOrDirectory(basePath + id);
        }
    }

    /**
     * 更新游戏信息
     * @param gameDTO
     */
    @Override
    public void update(GameDTO gameDTO) {
        Game game = new Game();
        BeanUtils.copyProperties(gameDTO, game);
        gameMapper.update(game);
    }

    /**
     * 通过id查找信息
     * @param id
     * @return
     */
    @Override
    public Game getById(Long id) {
        return gameMapper.getById(id);
    }

    /**
     * 通过publisherId查找游戏列表
     * @param publisherId
     * @return
     */
    @Override
    public List<Game> getByPublisherId(Long publisherId) {
        List<Game> list = gameMapper.getByPublisherId(publisherId);
        return list;
    }

    /**
     * 获取走马灯游戏卡片信息
     * @param gameCardDTO
     * @return
     */
    @Override
    public List<GameCarouselVO> getCarouselData(GameCardDTO gameCardDTO) {
        List<Game> gameList = gameMapper.getCarouselData(gameCardDTO);
        List<GameCarouselVO> list = new ArrayList<>();
        for (Game game : gameList) {
            GameCarouselVO gameCarousel = new GameCarouselVO();
            BeanUtils.copyProperties(game, gameCarousel);
            GamePrice gamePrice = gamePriceService.getByGameId(game.getId());
            GameDetail gameDetail = gameDetailService.getByGameId(game.getId());
            List<String> gameImageList = gameViewService.getGameImageViewOnCarouselByGameId(game.getId());
            gameCarousel.setGamePrice(gamePrice);
            gameCarousel.setPost(gameDetail.getPost());
            gameCarousel.setImageView(gameImageList);
            list.add(gameCarousel);

        }
        return list;
    }

    /**
     * 获取新品游戏卡片信息
     * @param gameCardDTO
     * @return
     */
    @Override
    public List<GameNewVO> getNewData(GameCardDTO gameCardDTO) {
        List<Game> gameList = gameMapper.getCarouselData(gameCardDTO);
        List<GameNewVO> list = getGameNewVOS(gameList);
        return list;
    }

    /**
     * 获取折扣游戏卡片信息
     * @param gameCardDTO
     * @return
     */
    @Override
    public List<GameDiscountVO> getDiscountData(GameCardDTO gameCardDTO) {
        List<Game> gameList = gameMapper.getDiscountData(gameCardDTO);
        List<GameDiscountVO> list = getGameDiscountVOS(gameList);
        return list;
    }

    /**
     * 获取游戏推荐卡片信息
     * @param gameCardDTO
     * @return
     */
    @Override
    public List<GameDiscountVO> getCommendData(GameCardDTO gameCardDTO) {
        List<Game> gameList = gameMapper.getCarouselData(gameCardDTO);
        List<GameDiscountVO> list = getGameDiscountVOS(gameList);
        return list;
    }

    /**
     * 分页查询热销、最新等数据
     * @param gameListPageQueryDTO
     * @return
     */
    @Override
    public PageResult getListData(GameListPageQueryDTO gameListPageQueryDTO) {
        PageHelper.startPage(gameListPageQueryDTO.getPage(), gameListPageQueryDTO.getPageSize());
        Page<Game> pageList = gameMapper.getBaseGameData(gameListPageQueryDTO);
        List<GameDiscountVO> list = getGameDiscountVOS(pageList.getResult());
        return new PageResult(pageList.getTotal(), list);
    }

    /**
     * 获取通用游戏走马灯信息
     * @param gameCardDTO
     * @return
     */
    @Override
    public List<GameCommonCarouselVO> getCommonCarouselData(GameCardDTO gameCardDTO) {
        if (gameCardDTO.getCategory() == null || gameCardDTO.getCategory().isEmpty()) {
            List<Game> gameList = gameMapper.getCarouselData(gameCardDTO);
            List<GameCommonCarouselVO> list = getGameCommonCarouselVOS(gameList);
            return list;
        } else {
            Category category = categoryService.getByName(gameCardDTO.getCategory());
            gameCardDTO.setCategory(category.getId().toString());
            List<Game> gameList = gameMapper.getCarouselDataByCategoryId(gameCardDTO);
            List<GameCommonCarouselVO> list = getGameCommonCarouselVOS(gameList);
            return list;
        }
    }

    @Override
    public List<GameNewVO> getGamesByCategoryId(GameCardDTO gameCardDTO) {
        List<Game> gameList = gameMapper.getCarouselDataByCategoryId(gameCardDTO);
        List<GameNewVO> list = getGameNewVOS(gameList);
        return list;
    }

    /**
     * 获取前端游戏详细信息
     * @param id
     * @return
     */
    @Override
    public GameFrontDetailVO getGameFrontDetailById(Long id) {
        // 1. 查询数据
        Game gameInDB = this.getById(id);
        GameViewListVO gameView = gameViewService.getGameViewWithIdByGameId(id);
        GameDetail gameDetail = gameDetailService.getByGameId(id);
        GamePublisherVO gamePublisher = publisherService.getPublisherByGameId(id);
        GamePrice gamePrice = gamePriceService.getByGameId(id);
        List<CategoryVO> gameCategory = categoryService.getCategoryByGameId(id);
        List<GameRequire> gameRequire = gameRequireService.getByGameId(id);
        // 2. 封装数据
        GameFrontVO game = new GameFrontVO();
        BeanUtils.copyProperties(gameInDB, game);
        GameFrontDetailVO gameFrontDetail = GameFrontDetailVO.builder()
                .game(game)
                .gameView(gameView)
                .gameDetail(gameDetail)
                .gamePublisher(gamePublisher)
                .gamePrice(gamePrice)
                .gameCategory(gameCategory)
                .gameRequire(gameRequire)
                .build();
        return gameFrontDetail;
    }

    /**
     * 获取购物车信息
     * @param id
     * @return
     */
    @Override
    public GameCartVO getGameOnCartByGameId(Long id) {
        Game game = this.getById(id);
        GameDetail gameDetail = gameDetailService.getByGameId(id);
        GamePrice gamePrice = gamePriceService.getByGameId(id);
        GameCartVO gameCartVO = GameCartVO.builder()
                .gameId(id)
                .chineseName(game.getChineseName())
                .englishName(game.getEnglishName())
                .widerPicture(gameDetail.getWiderPicture())
                .gamePrice(gamePrice)
                .build();
        return gameCartVO;
    }

    private List<GameNewVO> getGameNewVOS(List<Game> gameList) {
        List<GameNewVO> list = new ArrayList<>();
        for (Game game : gameList) {
            GameNewVO gameNewVO = new GameNewVO();
            BeanUtils.copyProperties(game, gameNewVO);
            GamePrice gamePrice = gamePriceService.getByGameId(game.getId());
            GameDetail gameDetail = gameDetailService.getByGameId(game.getId());
            gameNewVO.setGamePrice(gamePrice);
            gameNewVO.setHigherPicture(gameDetail.getHigherPicture());
            list.add(gameNewVO);
        }
        return list;
    }

    private List<GameCommonCarouselVO> getGameCommonCarouselVOS(List<Game> gameList) {
        List<GameCommonCarouselVO> list = new ArrayList<>();
        for (Game game : gameList) {
            GameCommonCarouselVO gameCommonCarousel = new GameCommonCarouselVO();
            BeanUtils.copyProperties(game, gameCommonCarousel);
            GamePrice gamePrice = gamePriceService.getByGameId(game.getId());
            GameDetail gameDetail = gameDetailService.getByGameId(game.getId());
            List<String> gameCategoryList = categoryService.getCategoryNameByGameId(game.getId());
            gameCommonCarousel.setGamePrice(gamePrice);
            gameCommonCarousel.setGameDetail(gameDetail);
            gameCommonCarousel.setCategory(gameCategoryList);
            list.add(gameCommonCarousel);
        }
        return list;
    }

    /**
     * 折扣游戏卡片和游戏推荐卡片内容是一样的，封装成方法
     * @param gameList
     * @return
     */
    private List<GameDiscountVO> getGameDiscountVOS(List<Game> gameList) {
        List<GameDiscountVO> list = new ArrayList<>();
        for (Game game : gameList) {
            GameDiscountVO gameDiscountVO = new GameDiscountVO();
            BeanUtils.copyProperties(game, gameDiscountVO);
            GamePrice gamePrice = gamePriceService.getByGameId(game.getId());
            GameDetail gameDetail = gameDetailService.getByGameId(game.getId());
            List<String> gameImageList = gameViewService.getGameImageViewOnCarouselByGameId(game.getId());
            List<String> gameCategoryList = categoryService.getCategoryNameByGameId(game.getId());
            gameDiscountVO.setGamePrice(gamePrice);
            gameDiscountVO.setWiderPicture(gameDetail.getWiderPicture());
            gameDiscountVO.setImageView(gameImageList);
            gameDiscountVO.setCategory(gameCategoryList);
            list.add(gameDiscountVO);
        }
        return list;
    }

    /**
     * 当前管理员权限判断
     *
     * @return
     */
    private Boolean adminPermission() {
        Integer permission = AdminContext.getCurrentStatus();
        if (permission != 0) {
            throw new AccountPermissionInsufficientException(MessageConstant.PERMISSION_INSUFFICIENT);
        }
        return true;
    }
}
